package jdk8.stream.sream1;

import jdk8.lambda.lambda2.Employee;
import jdk8.lambda.lambda2.EmployeeData;
import org.junit.Test;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

/**
 * @author Aunean
 * @date 2022/1/13 22:12
 */
/*
测试 Stream 的终止操作
 */
public class StreamAPITest2 {

    //1-匹配与查找
    @Test
    public void test1() {
        List<Employee> employees = EmployeeData.getEmployees();

        //allMatch(Predicate p)：检查是否匹配所有元素
        //练习：是否所有的员工的年龄都大于18
        boolean allMatch = employees.stream().allMatch(t -> t.getAge() > 18);
        System.out.println(allMatch);

        //anyMatch(Predicate p)：检查是否至少匹配一个元素
        boolean anyMatch = employees.stream().anyMatch(t -> t.getSalary() > 4000);
        System.out.println(anyMatch);

        //noneMatch(Predicate p)：检查是否没有匹配所有元素
        boolean noneMatch = employees.stream().noneMatch(t -> t.getName().startsWith("雷"));
        System.out.println(noneMatch);

        //findFirst()：返回第一个元素
        Optional<Employee> first = employees.stream().findFirst();
        System.out.println(first);

        //findAny()：返回当前流中的任意元素
        Optional<Employee> any = employees.parallelStream().findAny();
        System.out.println(any);
    }

    @Test
    public void test2() {
        List<Employee> employees = EmployeeData.getEmployees();
        //count()：返回流中元素总数
        long count = employees.stream().filter(e -> e.getSalary() > 5000).count();
        System.out.println(count);

        //max(Comparator c)：返回流中最大值
        //练习：求最高的工资
        Optional<Double> max = employees.stream().map(Employee::getSalary).max(Double::compare);
        System.out.println(max);

        //min(Comparator c)：返回流中最小值
        //练习：求最低工资的员工
        Optional<Employee> min = employees.stream().min(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(min);

        //forEach(Consumer c)：内部迭代(使用 Collection 接口需要用户去做迭代，为外部迭代。相反，Stream API 使用内部迭代——它帮你把迭代做了)
        employees.stream().forEach(System.out::println);
        //使用集合的遍历操作
        employees.forEach(System.out::println);
    }

    //2-规约
    @Test
    public void test3() {
        //reduce(T iden, BinaryOperator b)：可以将流中元素反复结合起来，得到一值。返回 T
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer reduce = list.stream().reduce(0, Integer::sum);
        System.out.println(reduce);

        //reduce(BinaryOperator b)：可以将流中元素反复结合起来，得到一个值。返回 Optional<T>
        //练习：计算公司所有员工工资的总和
        List<Employee> employees = EmployeeData.getEmployees();
        Double reduce1 = employees.stream().map(Employee::getSalary).reduce((double) 0, Double::sum);
        System.out.println(reduce1);

        Optional<Double> reduce2 = employees.stream().map(Employee::getSalary).reduce(new BinaryOperator<Double>() {
            @Override
            public Double apply(Double aDouble, Double aDouble2) {
                return aDouble + aDouble2;
            }
        });
        System.out.println(reduce2);
    }

    //3-收集
    @Test
    public void test4() {
        //collect(Collector c)：将流转换为其他形式。接收一个 Collector接口的实现，用于给Stream中元素做汇总的方法
        //练习：查找工资大于六千的员工，结果返回一个List或Set
        List<Employee> employees = EmployeeData.getEmployees();
        List<Employee> collect = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
        collect.forEach(System.out::println);

        System.out.println("************************");

        Set<Employee> collect2 = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
        collect2.forEach(System.out::println);
    }
}
